package com.sc.core.make;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.sc.common.exception.MessageTipException;
import com.sc.core.configtion.ScConfiguration;
import com.sc.core.make.dto.MakeInfoDTO;
import com.sc.core.make.dto.MakeJoinTableDTO;
import com.sc.core.make.file.*;
import com.sc.core.util.Sc;
import com.sc.core.util.Translation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;

import java.io.File;
import java.nio.file.Files;
import java.util.*;

@Log4j2
@Component
@AllArgsConstructor
public class MasterMake {

    private final Translation translation;

    public static final String BR = "\r\n";
    public static final String CREATE_AT = "create_time";
    public static final String UPDATE_AT = "update_time";
    public static final String DELETE_AT = "delete_time";
    public static final String PRIMARY = "id";

    public static String retraction(int $number){
        return "    ".repeat($number);
    }

    public static String retraction(String before, int number){
        return before + retraction(number);
    }

    public static String retraction(int number, String after){
        return retraction(number) + after;
    }

    public String getDir() {
        return System.getProperty("user.dir");
    }

    public static String getPackageDir(String moduleName) {
        List<String> list = Arrays.stream(System.getProperty("java.class.path").split(";"))
                .filter(s -> s.contains(moduleName + File.separator + "target") && !s.endsWith(".jar"))
                .toList();

        if (list.size() != 1){
            throw new MessageTipException("找不到模块目录%s，或无法确定".formatted(moduleName));
        }

        String modulePath = list.get(0).replace("target" + File.separator + "classes", "");

        return modulePath;
    }

    public static String getMakeDir(String moduleName) {
        List<String> packageDir = new ArrayList<>(Arrays.asList(getPackageDir("admin"), "src", "main", "java"));

        packageDir.addAll(List.of("com", "sc", "admin"));
        packageDir.addAll(Arrays.asList(moduleName.split("\\.")));

        return String.join(File.separator, packageDir);
    }

    public static String getClassName(String input){
        if (input == null || input.isEmpty()) {
            return input;
        }

        StringBuilder result = new StringBuilder();
        String[] parts = input.split("_");

        for (String part : parts) {
            result.append(part.substring(0, 1).toUpperCase());
            result.append(part.substring(1).toLowerCase());
        }
        return result.toString();
    }

    public static String getPropertyName(String input){
        String propertyName = getClassName(input);
        return propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1);
    }

    public static String getClassnameByTableName(String tableName) {
        return MasterMake.getClassName(tableName.replace(Sc.getBean(ScConfiguration.class).getTablePrefix(), ""));
    }

    @SneakyThrows
    public List<String> make(MakeInfoDTO makeInfo) {
        ArrayList<String> message = new ArrayList<>();
        Map<String, Map<Integer, String>> enumMap = enumHandle(makeInfo);
        List<MakeJoinTableDTO> makeJoinTables = joinTableHandle(makeInfo);
        Map<String, String> enumTranslation = enumTranslation(enumMap);
        makeInfo.setClassname(getClassnameByTableName(makeInfo.getTableName()));
        makeInfo.setIdentity(StringUtils.firstToLowerCase(makeInfo.getClassname()));
        makeInfo.setPackageName("com.sc.admin." + makeInfo.getModuleName());

        if (makeInfo.getType().contains("Entity")){
            message.add("Entity：" + new Entity(makeInfo, enumMap, enumTranslation).make().getMessage());
        }
        if (makeInfo.getType().contains("Service")){
            message.add("Service：" + new Service(makeInfo).make().getMessage());
        }
        if (makeInfo.getType().contains("Mapper")){
            message.add("Mapper：" + new Mapper(makeInfo, makeJoinTables).make().getMessage());
        }
        if (makeInfo.getType().contains("Controller")){
            message.add("Controller：" + new Controller(makeInfo, enumMap).make().getMessage());
        }
        if (makeInfo.getType().contains("UI")){
            message.add("UI：" + new Template(makeInfo, enumMap).make().getMessage());
        }
        return message;
    }

    private List<MakeJoinTableDTO> joinTableHandle(MakeInfoDTO makeInfo) {
        ArrayList<MakeJoinTableDTO> joinTables = new ArrayList<>();
        makeInfo.getColumns().forEach(column -> {
            if (column.expand().size() != 1){
                return;
            }
            if (!column.expand().get(0).contains(":")) {
                return;
            }
            String[] joinInfo  = column.expand().get(0).split(":");
            String[] joinField = joinInfo[1].split("=");

            String tableName  = joinInfo[0];
            String primaryKey = joinField[0];
            String showField  = joinField[1];

            String tablePrefix = Sc.getBean(ScConfiguration.class).getTablePrefix();

            MakeJoinTableDTO joinTable = new MakeJoinTableDTO();
            joinTable.setTableAlias(tableName);
            joinTable.setTableName(tableName.startsWith(tablePrefix) ? tableName : tablePrefix + tableName);
            joinTable.setPrimaryKey(primaryKey);
            joinTable.setForeignKey(column.columnName());
            joinTable.setShowField(showField);

            joinTables.add(joinTable);
        });
        return joinTables;
    }

    private Map<String, Map<Integer, String>> enumHandle(MakeInfoDTO makeInfo){
        HashMap<String, Map<Integer, String>> enumMap = new HashMap<>();
        makeInfo.getColumns().forEach(column -> {
            if (column.expand().size() > 1){
                HashMap<Integer, String> propertyEnum = new HashMap<>();
                column.expand().forEach(expand -> {
                    String[] split = expand.split("=");
                    propertyEnum.put(Integer.parseInt(split[0]), split[1]);
                });
                enumMap.put(column.columnName(), propertyEnum);
            }
        });

        return enumMap;
    }

    private Map<String, String> enumTranslation(Map<String, Map<Integer, String>> enumMap){
        HashMap<String, String> translationWait = new HashMap<>();
        enumMap.forEach((key, value) -> {
            value.forEach((k, v) -> {
                translationWait.put(v, v);
            });
        });
        if (translationWait.isEmpty()){
            return new HashMap<>();
        }
        return translation.translation(translationWait.values().stream().toList());
    }


    public static String writeFile(String filePath, String content) {
        try {
            File file = new File(filePath);
            if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
                return "创建目录失败" + file.getParentFile();
            }
            Files.writeString(file.toPath(), content);
            return "成功";
        } catch (Exception e) {
            return "失败" + e.getMessage();
        }
    }
}
